#pragma once
using namespace std;
#include<iostream>
#include<string>
#include<ctime>
#include<cstdio>
#include<cstdarg>
#include<fstream>
#include<string.h>
#include<errno.h>
#include<mutex>
#include<cstdlib>


//日志等级
enum Leval
{
    DEBUG,
    INFO,
    WARING,
    ERROR,
    FATAL
};

string LevelToStr(int level)
{
    switch (level)
    {
    case DEBUG:
        return "DEBUG";
    case INFO:
        return "INFO";
    case WARING: 
        return "WARING";
    case ERROR:
        return "ERROR";
    case FATAL:
        return "FATAL";
    default:
        return "UNKNOWN";
    }
}

string GetCurTime()
{
    time_t t = time(nullptr);
    struct tm* tp = localtime(&t);
    char tmp[30] = {0};
    sprintf(tmp, "%d/%d/%d %02d:%02d:%02d",
            tp->tm_year+1900,
            tp->tm_mon+1,
            tp->tm_mday,
            tp->tm_hour,
            tp->tm_min,
            tp->tm_sec);
    return tmp;
}

//格式：【时间】【等级】【文件名/行号】【内容】......
mutex mx;
void LogMessage(string filename, int line, int level, const char* format, ...)
{
    string levelstr = LevelToStr(level);
    string timestr = GetCurTime();
    va_list args;
    va_start(args, format);
    char content[2048] = {0};
    vsnprintf(content, sizeof(content), format, args);
    va_end(args);

    string message = "[" + timestr + "]" +
                     "[" + levelstr + "]" +
                     "[" + filename + "]" + 
                     "[" + to_string(line) + "]" +
                     "> " + content;
    //输出
    lock_guard<mutex> lg(mx);
    cout << message << endl;
}

//__VA_ARGS__可变参数宏（C99引入），##允许可变参数的数量为零
#define LOG(level, format, ...) LogMessage(__FILE__, __LINE__, level, format, ##__VA_ARGS__)